#include "02_TaskQueue.h"

using std::cout;
using std::endl;
using std::unique_lock;
using std::function;

 #define LOG_WHERE() \
    std::clog << "[DEBUG] " << __FILE__ << ":" << __LINE__ << " (" << __FUNCTION__ << ")\n"


TaskQueue::TaskQueue(size_t capacity)
    :_capacity(capacity)
    ,_exitflag(false)
{}

TaskQueue::~TaskQueue()
{}

void TaskQueue::TaskPush(function<void()>&& task_ptr)
{
    // 1: 先加锁（阻塞直到拿到锁）
    unique_lock<std::mutex> lock(_mutex);

    // 2：若条件不满足，自动释放锁并休眠
    // -- 条件变量 根据条件 判断是否加锁或解锁
    // -- 由 锁 阻塞 线程运行
    _notFull.wait(lock, [this]{return !full();});

    // 3：条件满足后，锁已自动持有
    _que.push(std::move(task_ptr));

    // 4: 锁满足后，通知可能等待的消费者
    _notEmpty.notify_one();
}

function<void()> TaskQueue::TaskPop()
{
    // 1: 先加锁（阻塞直到拿到锁）
    unique_lock<std::mutex> lock(_mutex);

    // 2：若条件不满足，自动释放锁并休眠
    _notEmpty.wait(lock, [this]{return !empty() || _exitflag;});
    LOG_WHERE();

    if(!_exitflag){
        // 3：条件满足后，锁已自动持有
        function<void()> result = _que.front();
        _que.pop();
        // cout << "result = " << result << '\n';  // 还要重载，怪麻烦的

        // 4: 锁满足后，通知可能等待的生产者
        _notFull.notify_one();

        LOG_WHERE();
        return result;
    }

    LOG_WHERE();
    //return nullptr;
    return function<void()>{};
};

bool TaskQueue::empty()
{
    return _que.empty();
}

bool TaskQueue::full()
{
    return _que.size() == _capacity;
}

void TaskQueue::wakeup()
{
    _exitflag = true;
    _notFull.notify_all();
    _notEmpty.notify_all();
    LOG_WHERE();
}
